use std::any::Any;
use std::collections::HashMap;
use bytes::{BufMut, BytesMut};
use log::info;
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::json;
use rpc::{decode, RpcContext, RpcResult};
use rpc::codec::{RpcCodec};
use rpc::codec::json_codec::{RpcJsonCodec};

trait RouterExecutor {
    fn execute(&mut self, data: Vec<u8>, rpc_context: &RpcContext)-> RpcResult<()>;
}


/// p: 参数
/// R： 返回值
trait RouterBusinessExecutor<P, R> {

    fn execute(&mut self, p: P) -> RpcResult<R>;
}

/// 参数编码
trait RouterCoder<T> {

    fn decode(&self, object_coder: &mut dyn RpcCodec<T>, data: Vec<u8>) -> RpcResult<T>;

    fn encode(&self, object_coder: &mut dyn RpcCodec<T>, data: T) -> RpcResult<Vec<u8>>;
}


struct DemoRouterBusinessExecutor {

}

impl RouterBusinessExecutor<i32, String> for DemoRouterBusinessExecutor {
    fn execute(&mut self, p: i32) -> RpcResult<String> {
        Ok(format!("p:{}", p))
    }
}

impl RouterCoder<i32> for DemoRouterBusinessExecutor {
    fn decode(&self, object_coder: &mut dyn RpcCodec<i32>, data: Vec<u8>) -> RpcResult<i32> {
        let r = object_coder.decode(data)?;
        Ok(r)
    }

    fn encode(&self, object_coder: &mut dyn RpcCodec<i32>, r: i32) -> RpcResult<Vec<u8>> {
        object_coder.encode(&r)
    }
}


struct DemoRouterExecutor {

}

impl RouterExecutor for DemoRouterExecutor {
    fn execute(&mut self, data: Vec<u8>, rpc_context: &RpcContext) -> RpcResult<()> {
        let mut business_executor = DemoRouterBusinessExecutor {};
        let data = decode(rpc_context, data)?;
        let result = business_executor.execute(data)?;
        // let _ = DemoRouterBusinessExecutor::encode(&mut bytes_mut, result)?;
        // let header = RpcHeader::new("/test", 0);
        // let data = RpcData::new(header, result);
        // rpc_context.send_data(ChannelId::new(0), bytes)?;
        Ok(())
    }
}

struct Demo2RouterExecutor {}
impl RouterExecutor for Demo2RouterExecutor {
    fn execute(&mut self, _data: Vec<u8>, _rpc_context: &RpcContext) -> RpcResult<()> {
        todo!()
    }
}

#[test]
fn router_test() {
    let mut map: HashMap<&'static str, Box<dyn RouterExecutor>> = HashMap::new();
    map.insert("/demo", Box::new(DemoRouterExecutor { }));
    map.insert("/demo2", Box::new(Demo2RouterExecutor { }));
    let mut router = map.get_mut("/demo").unwrap();
    let mut bytes_mut = BytesMut::new();
    let d = 12;
    let json = serde_json::to_string(&d).unwrap();
    let value = json!(json);
    let dd: i32 = serde_json::from_str(&json).unwrap();
    bytes_mut.put_slice(json.as_bytes());
    let mut context = RpcContext::test_context_with_codec_type("json");
    context.set_current_codec_type(Some("json".to_string()));
    router.execute(bytes_mut.freeze().to_vec(), &mut context).unwrap();
}

#[test]
fn any_test() {
    let codec = any_demo::<i32>(Box::new(RpcJsonCodec::default()));
    any_demo2(Box::new(RpcJsonCodec::default()));
}

#[test]
fn add_rpc_codec_factory_test() {
    // add_rpc_codec_factory(Box::new(RpcJsonCodec::new()));
}

fn any_demo<T: Serialize + DeserializeOwned>(object_code: Box<dyn Any>) -> Option<Box<dyn RpcCodec<T>>> {
    let codec = object_code.downcast::<RpcJsonCodec>();
    match codec {
        Ok(codec) => {
            info!("success!!!!!!!!!!!!!!!!!!");
            Some(codec)
        }
        Err(_) => {
            info!("Not an object");
            None
        }
    }
}

fn any_demo2(object_code: Box<dyn Any>) {
    info!("ttt: {:?}", object_code);
    let t = object_code.is::<RpcJsonCodec>();
    let codec = object_code.downcast_ref::<RpcJsonCodec>();
    match codec {
        None => {
            info!("Not an object");
        }
        Some(_) => {
            info!("success!!!!!!!!!!!!!!!!!!");
        }
    }
}